package com.syg.boot.core.builder;

import com.syg.boot.core.common.EnvNameEnum;
import com.syg.boot.util.text.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author syg
 * @date 2021年11月24日15:31:51
 * @version 1.0
 *
 * 三种监听器的关系
 * ApplicationListener、SpringApplicationRunListeners、SpringApplicationRunListener的关系：
 *
 * SpringApplicationRunListeners类和SpringApplicationRunListener类是SpringBoot中新增的类。ApplicationListener是spring中框架的类。
 * 在SpringBoot（SpringApplication类）中，使用SpringApplicationRunListeners、SpringApplicationRunListener来间接调用ApplicationListener。
 * SpringApplicationRunListeners是SpringApplicationRunListener的封装，SpringApplicationRunListeners中包含多个SpringApplicationRunListener，是为了批量执行的封装，SpringApplicationRunListeners与SpringApplicationRunListener生命周期相同，调用每个周期的各个SpringApplicationRunListener。然后广播相应的事件到Spring框架的ApplicationListener。
 * 通过上面的3个特点可以看出SpringApplicationRunListener就是一个ApplicationListener的代理。springboot启动的几个主要过程的监听通知都是通过他来进行回调。
 */
public class SygSpringApplicationRunListener implements SpringApplicationRunListener, PriorityOrdered {
    private static final Logger log = LoggerFactory.getLogger(SygSpringApplicationRunListener.class);

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public void starting() {
        log.info("shenehneshenhe");
    }

    /**
     * ApplicationContext创建之前并且环境信息准备好的时候调用；对应事件的类型是ApplicationEnvironmentPreparedEvent)：通知监听器，Environment准备完成
     * @param environment
     */
    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
        log.info("environmentPreparedshen");
        Object key = YamlReader.INSTANCE.getValue("application.yml", "spring.profiles.active");
        List<String> list = this.getFields(String.valueOf(key));
        String activeProfile;
        String profile = null;
        if (StringUtils.isEmpty(list)) {
            log.error("application.yml中[spring.profiles.active]参数为空");
        } else {
            activeProfile = list.get(0).split(":")[1];
            profile = EnvNameEnum.getProfile(activeProfile.split(","));
            log.info("application.yml中[spring.profiles.active]值为:{}", profile);
        }

        activeProfile = System.getProperty("spring.profiles.active");
        log.info("启动参数中[spring.profiles.active]值为:{}", activeProfile);
        if (StringUtil.isNotEmpty(activeProfile)) {
            profile = activeProfile;
        }
        if (StringUtil.isEmpty(profile)) {
            log.error("activeProfile is empty");
        }else {
            log.debug("current environment：{}", profile);
            environment.addActiveProfile("global-"+profile);
            environment.addActiveProfile("ds-" + profile);
            Object system = YamlReader.INSTANCE.getValue("application.yml", "zsf.boot.ds.dbNamePrefix");
            if (system != null) {
                environment.addActiveProfile("ds-" + profile + "-" + system);
            }

            environment.addActiveProfile("project-" + profile);
        }


    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {

    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {

    }

    @Override
    public void started(ConfigurableApplicationContext context) {

    }

    @Override
    public void running(ConfigurableApplicationContext context) {

    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {

    }


    private List<String> getFields(String sql) {
        return this.getFields("$", sql);
    }

    private List<String> getFields(String prefix, String sql) {
        List<String> list = new ArrayList<>();
        Pattern regex = Pattern.compile("\\" + prefix + "\\{([^}]*)\\}");
        Matcher matcher = regex.matcher(sql);

        while(matcher.find()) {
            list.add(matcher.group(1));
        }

        return list;
    }
}
